package cn.likun.kit.string;

import java.io.UnsupportedEncodingException;
import cn.likun.kit.datacast.CastCommons;
import cn.likun.kit.easyparam.ParamMap;
import cn.likun.kit.placeholder.PlaceholderCommons;
import cn.likun.kit.validate.ValidateCommons;

/**
 * @作者 SUCH
 * @日期 2017-3-13 下午7:11:15
 * @描述 字符串
 */
public class StringCommons {

	public static final String ENCODE_UTF8 = "UTF-8";
	public static final String VALUE_PLACEHOLDER = "#[value]";
	
	/**  
     * 将数组按一定规则拼装为字符串 
     * @param array 需处理数组 
     * @param rule 规则，值使用占位符 VALUE_PLACEHOLDER 代替，可在值的前后插入一些字符串，如  VALUE_PLACEHOLDER, 
     * @param beginIndex 对生成的字符串从头部去掉几个字符 
     * @param endIndex 对生成的字符串从尾部去掉几个字符
     */
	public static String merger(Object[] array, String rule, int beginIndex, int endIndex) {
		String str = "";
		StringBuffer strBuf = new StringBuffer();
		if (ValidateCommons.isNotEmpty(array)) {
			for (Object obj : array) {
				strBuf.append(PlaceholderCommons.replacePlaceholder(rule, new ParamMap<String, String>().putParam("value", obj.toString())));
			}
		}
		str = strBuf.toString();
		int length = str.length();
		if (length > 0) {
			if (length >= beginIndex) {
				str = str.substring(beginIndex, length);
				length = str.length();
			}
			if (length >= endIndex) {
				str = str.substring(0, length - endIndex);
			}
		}
		return str;
	}
	
	/**  
     * 将数组以符号分割拼装为字符串 
     * @param array 需处理数组 
     * @param separator 分割符 
     * @param cutLastSeparator 是否去除尾部的分割符
     */
	public static String merger(Object[] array, String separator, boolean cutLastSeparator) {
		String rule = new StringBuffer(VALUE_PLACEHOLDER).append(separator).toString();
		int endIndex = 0;
		if (cutLastSeparator) {
			endIndex = separator.length();
		}
		return merger(array, rule, 0, endIndex);
	}

	/**
	 * <p>方法名：merger</p>
	 * <p>描述：将数组拼装为字符串</p>
	 * @param array 需处理数组
	 * @return
	 */
	public static String merger(Object... array) {
		StringBuffer buf = new StringBuffer();
		if (ValidateCommons.isNotEmpty(array)) {
			for (Object obj : array) {
				buf.append(obj);
			}
		}
		return buf.toString();
	}

	/**  
     * 计算字符串长度 
     * @param str 需处理字符串 
     * @param encode 编码 
     * @param useStrictlyLength 是否使用严格计算，为 true 时会对方块字作多位处理
     */
	public static int length(String str, String encode, boolean useStrictlyLength) {
		int length = 0;
		if (ValidateCommons.isNotEmpty(str)) {
			if (useStrictlyLength) {
				byte[] byteArray = CastCommons.stringToBytes(str, encode);
				length = byteArray.length;
			} else {
				length = str.length();
			}
		}
		return length;
	}

	/**  
     * 计算字符串长度 
     * @param str 需处理字符串 
     * @param useStrictlyLength 是否使用严格计算，为 true 时会对方块字作多位处理
     */
	public static int length(String str, boolean useStrictlyLength) {
		return length(str, null, useStrictlyLength);
	}

	/**  
     * 截取字符串长 
     * @param str 需处理字符串 
     * @param begin 开始位置 
     * @param end 结束位置，当字符串长度小于截取长度，则不作处理 
     * @param encode 编码，当编码未找到则使用默认编码 
     * @param useStrictlySub 是否使用严格截取，为 true 时会对方块字作多位处理
     */
	public static String substring(String str, int begin, int end, String encode, boolean useStrictlySub) {
		if (ValidateCommons.isNotEmpty(str)) {
			if (useStrictlySub) {
				byte[] byteArray = CastCommons.stringToBytes(str, encode);
				int length = byteArray.length;
				if (length > begin && length > end) {
					byteArray = copyOfRange(byteArray, begin, end);
					if (ValidateCommons.isEmpty(encode)) {
						str = new String(byteArray);
					} else {
						try {
							str = new String(byteArray, encode);
						} catch (UnsupportedEncodingException e) {
							str = new String(byteArray);
						}
					}
				}
			} else {
				int length = str.length();
				if (length > end) {
					str = str.substring(begin, end);
				}
			}
		}
		return str;
	}

	/**  
     * 截取字符串长 
     * @param str 需处理字符串 
     * @param begin 开始位置 
     * @param end 结束位置 
     * @param useStrictlySub 是否使用严格截取，为 true 时会对方块字作多位处理
     */
	public static String substring(String str, int begin, int end, boolean useStrictlySub) {
		return substring(str, begin, end, null, useStrictlySub);
	}

	/**  
     * 按照字符串位（方块字占多位 GBK 占二位，UTF-8 占三位）截取字符串 
     * @param str 需处理字符串 
     * @param begin 开始位置 
     * @param end 结束位置 
     * @param encode 编码
     */
	public static String substring(String str, int begin, int end, String encode) {
		return substring(str, begin, end, encode, true);
	}

	/**  
     * 按照字符串位（方块字占多位 GBK 占二位，UTF-8 占三位）截取字符串 
     * @param str 需处理字符串 
     * @param begin 开始位置 
     * @param end 结束位置
     */
	public static String substring(String str, int begin, int end) {
		return substring(str, begin, end, null, true);
	}

	/**  
     * 截取数组
     * @param original 原数组 
     * @param from 开始位置 
     * @param to 结束位置，当 to 大于 from或数组长度小于截取长度，则不作处理
     */
	public static byte[] copyOfRange(byte[] original, int from, int to) {
		int copyLen = to - from;
		if (copyLen <= 0) {
			return original;
		}
		int len = original.length;
		if (len <= from || len <= to) {
			return original;
		}
		byte[] copy = new byte[copyLen];
		System.arraycopy(original, from, copy, 0, Math.min(len - from, copyLen));
		return copy;
	}

	/**  
     * 格式化字符串长度，将字符串格式到统一长度，当字符串长度不过，在后面补空格 
     * @param str 需处理字符串 
     * @param len 统一转换后的字符串长度 
     * @param encode 编码 
     * @param useStrictlyLength 是否使用严格截取，为 true 时会对方块字作多位处理
     */
	public static String formatStringLength(String str, Integer len, String encode, boolean useStrictlyLength) {
		int valLen = length(str, encode, useStrictlyLength);
		if (len > valLen) {
			for (int i = valLen; i < len; i++) {
				str += ' ';
			}
		}
		return str;
	}

	/**  
     * 格式化字符串长度，将字符串格式到统一长度，当字符串长度不过，在后面补空格 
     * @param str 需处理字符串 
     * @param len 统一转换后的字符串长度 
     * @param useStrictlyLength 是否使用严格截取，为 true 时会对方块字作多位处理
     */
	public static String formatStringLength(String str, Integer len, boolean useStrictlyLength) {
		int valLen = length(str, null, useStrictlyLength);
		if (len > valLen) {
			for (int i = valLen; i < len; i++) {
				str += ' ';
			}
		}
		return str;
	}

}
